#include <iostream>
#include <string>
#include <unistd.h>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "err.hpp"

using namespace std;

static void usage(char *argv)
{
    cout << "Usage:\n\t" << argv << " serverIp serverPort" << endl;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }

    string serverIp = argv[1];
    uint16_t serverPort = atoi(argv[2]);

    // 1.创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        cerr << "create sock error," << strerror(errno) << endl;
        exit(SOCKET_ERR);
    }

    cout<<"create sock sucess:"<<sock<<endl;

    // 2. 连接
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(serverIp.c_str());
    server.sin_port = htons(serverPort);

    int cnt = 5; // 记录重连次数
    // connect时会bind
    while (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        cout << "正在重连...还有" << cnt-- << "次" << endl;
        if (cnt <= 0)
        {   
            cerr<<"连接失败"<<endl;
            exit(CONNECT_ERR);
        }
        sleep(1);
    }

    // 连接成功
    string name = "["+serverIp + ":" + to_string(serverPort)+"]";
    cout << "connect " << name << " sucess" << endl;

    // 发送消息
    while (true)
    {
        cout << "please enter your message# ";
        string message;
        getline(cin, message);

        int n = write(sock, message.c_str(), message.size());
        if (n < 0)
        {
            cerr << "write error," << strerror(errno) << endl;
            break;
        }
        else if (n == 0)
        {
            cout << "读端关闭，停止写" << endl;
            break;
        }

        char buffer[1024];
        int m = read(sock, buffer, sizeof(buffer) - 1);
        if (m > 0)
        {
            buffer[n] = '\0';
            cout<<name<<" echo "<<buffer<<endl;
        }
        else if (m == 0)
        {
            // 写端关闭
            std::cout << name << " quit,me to" << std::endl;
            close(sock);
            break;
        }
        else
        {
            // 读数据异常
            std::cerr << "read error" << std::endl;
            break;
        }
    }

    return 0;
}